1
1
.
.
1
1
1
1
.
.
5
5
S
S
t
t
e
e
p
p
5
5
-
-
F
F
i
i
l
l
t
t
e
e
r
r
I
I
n
n
f
f
o
o
[
[
G
G
]
]
In this tutorial we will add Filter that for each Request creates Authentication Object with Username and Authorities.
Authentication Object is then stored into Context so that it can be used to control access to MyController Endpoints.
Username and Role are contained inside JWT so there is no need to go into DB to get Roles/Authorities for the User.
Application Schema [Results]
O
O
v
v
e
e
r
r
v
v
i
i
e
e
w
w
MyFilter.java
@Component
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain) {
//GET AUTHORIZATION HEADER
String authorizationHeader = httpRequest.getHeader("Authorization");
if(authorizationHeader != null) {
//EXTRACT JWT FROM AUTHORIZATION HEADER
MyController
http://localhost:8080/CreateJWT
Tomcat
createJWT()
Postman
MyFilter
createBook()
WebSecurityConfig
P
P
r
r
o
o
c
c
e
e
d
d
u
u
r
r
e
e
Edit File: pom.xml (Add Security dependency)
Inside Package: controllers
– Create Class: MyController.java (Add restricted Endpoint "/Hello")
Inside Package: config
– Create Class: MyFilter.java (Store Authentication into Context)
– Create Class: WebSecurityConfig.java (Restrict access to Endpoint "/Hello")
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
MyController.java
package com.ivoronline.springboot_security_jwt.controllers;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@ResponseBody
@PreAuthorize("hasAuthority('book.create')")
@RequestMapping("/CreateBook")
public String createBook() {
return "Only ADMIN can create Book";
}
}
MyFilter.java
package com.ivoronline.springboot_demo_jwtauthoritiesfromdb.security.jwt;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Component
public class MyFilter implements Filter {
@Autowired private JWTUtil jwtUtil;
//==================================================================================
// DO FILTER
//==================================================================================
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterchain)
throws IOException, ServletException {
//CAST REQUEST TO GET ACCESS TO HEADERS
HttpServletRequest httpRequest = (HttpServletRequest) request;
//GET AUTHORIZATION HEADER
String authorizationHeader = httpRequest.getHeader("Authorization");
//IF AUTHORIZATION HEADER PRESENT USE JWT TO PUT AUTHENTICATION OBJECT INTO CONTEXT
if(authorizationHeader != null) { addAuthenticationObjectIntoContext(authorizationHeader); }
//FORWARD REQUEST
filterchain.doFilter(request, response);
}
//==================================================================================
// ADD AUTHENTICATION OBJECT INTO CONTEXT
//==================================================================================
private void addAuthenticationObjectIntoContext(String authorizationHeader) {
//EXTRACT JWT FROM AUTHORIZATION HEADER
String jwt = jwtUtil.extractJWTFromAuthorizationHeader(authorizationHeader);
//GET CLAIMS
Claims claims = jwtUtil.getClaims(jwt);
String username = (String) claims.get("username");
String authoritiesJWT = (String) claims.get("authorities"); //"[book.read, book.delete]"
//CREATE AUTHORITIES
String authoritiesString = authoritiesJWT.replace("[","").replace("]","").replace(" ","");
String[] authoritiesArray = authoritiesString.split(",");
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(String authority : authoritiesArray) {
authorities.add(new SimpleGrantedAuthority(authority));
}
//AUTHENTICATE
Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, authorities);
//STORE AUTHENTICATION INTO CONTEXT (SESSION)
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
WebSecurityConfig.java
package com.ivoronline.springboot_security_jwt.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired private MyFilter myFilter;
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//ANONYMOUS ACCESS
httpSecurity.authorizeRequests().antMatchers("/CreateJWT" ).permitAll(); //To get JWT
httpSecurity.authorizeRequests().antMatchers("/GetClaims" ).permitAll(); //For Testing
httpSecurity.authorizeRequests().antMatchers("/GetUsername").permitAll(); //For Testing
//OTHER CONFIGURATION
httpSecurity.csrf().disable(); //Enables POST
httpSecurity.authorizeRequests().anyRequest().authenticated(); //Authenticated
httpSecurity.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class); //Add Filter
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); //No Session
}
}
R
R
e
e
s
s
u
u
l
l
t
t
s
s
http://localhost:8080/CreateJWT
P
P
o
o
s
s
t
t
m
m
a
a
n
n
GET
http://localhost:8080/CreateBook
Headers (add Key-Value)
Authorization: Bearer
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJUZXN0SldUIiwicm9sZSI6IlJPTEVfVVNFUiIsImlzcyI6Iml2b3JvbmxpbmUiLCJqdGkiOiIxIiwi
dXNlcm5hbWUiOiJteXVzZXIifQ.g7CcreAHQvSR1JjQJqTBvT3eGcpz9kcuVOkgUFREiIc
Postman